package mallindex

import (
	"context"
	"strconv"
	"strings"

	// "fmt"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/utils/pointy"
	"mall/service/backend/rpc/backendclient"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/product/rpc/productclient"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetLiveTileByIdLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetLiveTileByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLiveTileByIdLogic {
	return &GetLiveTileByIdLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetLiveTileByIdLogic) GetLiveTileById(
	req *types.LiveTileIdReq,
	headers *[]*types.Header,
) (*types.GoodsSectionInfo, error) {
	if req.Id == nil || *req.Id == 0 {
		return &types.GoodsSectionInfo{}, nil
	}

	userId := jwt.GetUserId(l.ctx)

	preload := "section:Id,Title,Subtitle,PicId,PicUrl"
	eagerLoad := "section:sectionProduct"
	preload += ";sectionProduct:SectionId,BrandId,CategoryId,ProductId"

	res, err := l.svcCtx.BackendRpc.GetSectionById(l.ctx, &backendclient.BaseIdReq{
		Id:         req.Id,
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
	})
	if err != nil {
		logx.Errorw("GetLiveTileById err", logx.Field("detail", err.Error()))
		return &types.GoodsSectionInfo{}, nil
	}

	if res == nil || res.Id == nil || *res.Id == 0 {
		return &types.GoodsSectionInfo{}, nil
	}

	var pids []string
	var bids []string
	var cids []string
	for pid, pType := range res.ProductIdMap {
		switch pType {
		case 1:
			pids = append(pids, strconv.FormatUint(pid, 10))
		case 2:
			bids = append(bids, strconv.FormatUint(pid, 10))
		case 3:
			cids = append(cids, strconv.FormatUint(pid, 10))
		}
	}

	var pageSize uint64
	var products []*types.GoodsInfo
	var brands []*types.KbEntryInfo
	if len(pids) > 0 || len(bids) > 0 || len(cids) > 0 {
		products, err = l.getProductListByIds(pids, bids, cids, pageSize)
		if err != nil {
			return nil, err
		}
	}

	if len(bids) > 0 {
		brands, err = l.getEntryList(userId, bids)
		if err != nil {
			return nil, err
		}
	}

	return &types.GoodsSectionInfo{
		Id:        res.Id,
		Title:     res.Title,
		Subtitle:  res.Subtitle,
		ImageUrl:  res.PicUrl,
		GoodsList: products,
		BrandList: brands,
	}, nil
}

func (l *GetLiveTileByIdLogic) getProductListByIds(pids []string, bids []string, cids []string, limit uint64) (resp []*types.GoodsInfo, err error) {
	preload := "product:Id,Title,Slug"
	eagerLoad := "product:productMeta,productMedia"
	preload += ";productMeta:mediaId,mediaUrl,retailPriceMin"
	preload += ";productMedia:Uid,Url"

	var filters []string
	filters = append(filters, "virtual,equalTo:"+strconv.FormatInt(int64(globalkey.ProductTypePhysical), 10))
	filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.StatusEnabled), 10))
	filters = append(filters, "Id,in:"+strings.Join(pids, ","))

	var preFilterEntity string
	var preFilter string
	if len(bids) > 0 { // 指定品牌ID
		preFilterEntity = "productRelationship"
		preFilter = "BrandId,in:" + strings.Join(bids, ",")
	} else if len(cids) > 0 {
		preFilterEntity = "productTerm"
		preFilter = "Id,in:" + strings.Join(cids, ",")
	}

	res, err := l.svcCtx.ProductRpc.GetProductList(l.ctx, &productclient.BaseListReq{
		Preload:         pointy.GetPointer(preload),
		EagerLoad:       pointy.GetPointer(eagerLoad),
		PreFilterEntity: pointy.GetPointer(preFilterEntity),
		PreFilter:       pointy.GetPointer(preFilter),
		Filter:          pointy.GetPointer(strings.Join(filters, ";")),
	})
	if err != nil {
		return nil, err
	}

	if len(res.List) > 0 {
		var count uint64 = 1
		for _, v := range res.List {
			if limit > 0 && count > limit {
				break
			}

			count += 1

			// logrus.Info(fmt.Sprintf("GetLiveTileList getProductListByIds GetProductList res.List: %+v", v))
			var retailPriceMin *string
			var mediaUrl *string
			if len(v.Meta) > 0 {
				for _, m := range v.Meta {
					if m.Key == nil || m.Value == nil {
						continue
					}

					val := *m.Value
					switch *m.Key {
					case "retailPriceMin":
						retailPriceMin = pointy.GetPointer(val)
					case "mediaUrl":
						mediaUrl = pointy.GetPointer(val)
					}
				}
			}

			if len(v.Media) > 0 {
				for _, m := range v.Media {
					if mediaUrl != nil {
						break
					}

					var url string
					if m.Url != nil && len(*m.Url) > 0 {
						url = *m.Url
					}
					if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
						url = *m.Uri
					}
					mediaUrl = pointy.GetPointer(url)
				}
			}

			resp = append(resp, &types.GoodsInfo{
				Id:       v.Id,
				Title:    v.Title,
				Slug:     v.Slug,
				MinPrice: retailPriceMin,
				ImageUrl: mediaUrl,
			})
		}
	}

	return resp, nil
}

func (l *GetLiveTileByIdLogic) getEntryList(
	userId uint64,
	bids []string,
) (resp []*types.KbEntryInfo, err error) {
	preload := "blogBook:Id,Title,Slug,SectionId"
	eagerLoad := "blogBook:blogBookMeta,blogMedia"
	preload += ";blogBookMeta:mediaUrl"
	preload += ";blogMedia:Uid,Url"
	filters := []string{"Status,equalTo:" + strconv.FormatInt(int64(globalkey.PostStatusPublish), 10)}
	if len(bids) > 0 {
		filters = append(filters, "Id,in:"+strings.Join(bids, ","))
	}

	res, err := l.svcCtx.BlogRpc.GetKBPostListTmp(l.ctx, &blogclient.BaseListReq{
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		Filter:     pointy.GetPointer(strings.Join(filters, ";")),
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
	})
	if err != nil {
		return nil, err
	}

	if len(res.List) == 0 {
		return nil, nil
	}

	if len(res.List) > 0 {
		for _, v := range res.List {
			var mediaUrl *string
			var reviewCount *uint32
			if len(v.Meta) > 0 {
				for _, m := range v.Meta {
					if m.Key == nil || m.Value == nil {
						continue
					}

					val := *m.Value
					switch *m.Key {
					case "mediaUrl":
						mediaUrl = pointy.GetPointer(val)
					case "reviewCount":
						if i, err := strconv.ParseInt(val, 10, 32); err == nil {
							reviewCount = pointy.GetPointer(uint32(i))
						}
					}
				}
			}

			if len(v.Media) > 0 {
				for _, m := range v.Media {
					if mediaUrl != nil {
						break
					}

					var url string
					if m.Url != nil && len(*m.Url) > 0 {
						url = *m.Url
					}
					if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
						url = *m.Uri
					}
					mediaUrl = pointy.GetPointer(url)
				}
			}

			resp = append(resp, &types.KbEntryInfo{
				Id:          v.Id,
				Title:       v.Title,
				Slug:        v.Slug,
				ImageUrl:    mediaUrl,
				ReviewCount: reviewCount,
				SectionId:   v.SectionId,
			})
		}
	}

	return resp, nil
}
